Load necessary packages, load data.

#load necessary packages:
library(car)
library(tidyverse)
library(caret)
library(multiUS)
library(boot)
library(ggplot2)
library(ggpubr)
library(readr)
library(corrplot)
library(olsrr)
library(MASS)
library(car)


#Load Data

data=read.csv('https://raw.githubusercontent.com/anishkapeter/Stat1Project/main/train.csv')

Fill missing values in numeric columns with KNN imputation

numeric_cols <- names(data)[sapply(data, is.numeric)]
#colSums(is.na(data[,numeric_cols]))
#mode(data$LotFrontage)


categorical_cols <- names(data)[sapply(data, is.character)]
#length(categorical_cols)+length(numeric_cols)
numeric_data <- data[, numeric_cols]
numeric_data_imputed <- KNNimp(as.matrix(numeric_data))  # convert data frame to matrix for knnImpute
data[numeric_cols] <- numeric_data_imputed

combine training and test data together, for easier cleaning

url <- "https://github.com/anishkapeter/Stat1Project/blob/main/test.csv?raw=true"
test <- read.csv(url)

data_c <- subset(data, select = -c(SalePrice))
saleprice = data$SalePrice
# Combine the data and test dataframes
combined_data <- rbind(data_c, test)

Define ordinal columns, regroup character columns and apply factor encoding.

# Identify character columns



combined_data$ExterCond <- factor(combined_data$ExterCond, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$ExterCond <- as.numeric(combined_data$ExterCond)
combined_data$ExterQual <- factor(combined_data$ExterQual, levels = c("Fa", "TA", "Gd", "Ex"))
combined_data$ExterQual <- as.numeric(combined_data$ExterQual)


# First, ensure NA values are not treated as missing data
combined_data$BsmtQual <- addNA(combined_data$BsmtQual)
combined_data$BsmtCond <- addNA(combined_data$BsmtCond)
combined_data$BsmtQual <- factor(combined_data$BsmtQual, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$BsmtCond <- factor(combined_data$BsmtCond, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$BsmtQual <- as.numeric(combined_data$BsmtQual)
combined_data$BsmtCond <- as.numeric(combined_data$BsmtCond)



# First, ensure NA values are not treated as missing data
combined_data$GarageCond <- addNA(combined_data$GarageCond)
combined_data$GarageQual <- addNA(combined_data$GarageQual)
combined_data$GarageCond <- factor(combined_data$GarageCond, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$GarageQual <- factor(combined_data$GarageQual, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$GarageCond <- as.numeric(combined_data$GarageCond)
combined_data$GarageQual <- as.numeric(combined_data$GarageQual)



# Convert NA values to factor levels
combined_data$PoolQC <- addNA(combined_data$PoolQC)
combined_data$FireplaceQu <- addNA(combined_data$FireplaceQu)
combined_data$HeatingQC <- addNA(combined_data$HeatingQC)
combined_data$KitchenQual <- addNA(combined_data$KitchenQual)
combined_data$BsmtExposure <- addNA(combined_data$BsmtExposure)
combined_data$PoolQC <- factor(combined_data$PoolQC, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$FireplaceQu <- factor(combined_data$FireplaceQu, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$HeatingQC <- factor(combined_data$HeatingQC, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$KitchenQual <- factor(combined_data$KitchenQual, levels = c("Po", "Fa", "TA", "Gd", "Ex"))
combined_data$BsmtExposure <- factor(combined_data$BsmtExposure, levels = c("No", "Mn", "Av", "Gd"))
combined_data$PoolQC <- as.numeric(combined_data$PoolQC)
combined_data$FireplaceQu <- as.numeric(combined_data$FireplaceQu)
combined_data$HeatingQC <- as.numeric(combined_data$HeatingQC)
combined_data$KitchenQual <- as.numeric(combined_data$KitchenQual)
combined_data$BsmtExposure <- as.numeric(combined_data$BsmtExposure)



# Convert NA values to factor levels
combined_data$BsmtFinType1 <- addNA(combined_data$BsmtFinType1)
combined_data$BsmtFinType2 <- addNA(combined_data$BsmtFinType2)
combined_data$Fence <- addNA(combined_data$Fence)
combined_data$GarageFinish <- addNA(combined_data$GarageFinish)
combined_data$Alley <- addNA(combined_data$Alley)

#table(combined_data$Alley)

combined_data$BsmtFinType1 <- factor(combined_data$BsmtFinType1, levels = c("Unf", "LwQ", "Rec", "BLQ", "ALQ", "GLQ"))
combined_data$BsmtFinType2 <- factor(combined_data$BsmtFinType2, levels = c("Unf", "LwQ", "Rec", "BLQ", "ALQ", "GLQ"))
combined_data$CentralAir <- factor(combined_data$CentralAir, levels = c("N", "Y"))
combined_data$Fence <- factor(combined_data$Fence, levels = c("MnWw", "GdWo", "MnPrv", "GdPrv"))
combined_data$GarageFinish <- factor(combined_data$GarageFinish, levels = c("Unf", "RFn", "Fin"))
combined_data$Alley <- factor(combined_data$Alley, levels = c("Grvl", "Pave"))
combined_data$LotShape <- factor(combined_data$LotShape, levels = c("Reg", "IR1", "IR2", "IR3"))
combined_data$LandSlope <- factor(combined_data$LandSlope, levels = c("Gtl", "Mod", "Sev"))

combined_data$BsmtFinType1 <- as.numeric(combined_data$BsmtFinType1)
combined_data$BsmtFinType2 <- as.numeric(combined_data$BsmtFinType2)
combined_data$CentralAir <- as.numeric(combined_data$CentralAir)
combined_data$Fence <- as.numeric(combined_data$Fence)
combined_data$GarageFinish <- as.numeric(combined_data$GarageFinish)
combined_data$Alley <- as.numeric(combined_data$Alley)
combined_data$LotShape <- as.numeric(combined_data$LotShape)
combined_data$LandSlope <- as.numeric(combined_data$LandSlope)




ordinal_cols <- c('ExterQual', 'ExterCond', 'BsmtQual', 'BsmtCond', 
                  'GarageCond', 'GarageQual', 'PoolQC', 'FireplaceQu', 
                  'HeatingQC', 'KitchenQual', 'BsmtExposure', 'BsmtFinType1', 
                'BsmtFinType2', 'CentralAir', 'Fence','GarageFinish','Alley','LotShape','LandSlope')

#table(data$ExterQual)


combined_data[ordinal_cols] <- lapply(combined_data[ordinal_cols], function(x) replace(x, is.na(x), 0))





# Transform ordinal columns into factors and replace NA with 0

#data[ordinal_cols] <- lapply(data[ordinal_cols], function(x) {
#  x <- as.factor(x)
#  levels(x) <- c(levels(x), "0")
# x[is.na(x)] <- "0"
#  return(x)
# })

# Checking all character columns
#colnames(data)[colSums(is.na(data)) > 0]




# Threshold for 'rare' observations
n <- 10 

# Loop through the character columns
for (col_name in colnames(combined_data)[sapply(combined_data, is.character)]) {
  # Convert rare observations to 'Other'
  combined_data[[col_name]] <- ifelse(combined_data[[col_name]] %in% names(which(table(combined_data[[col_name]]) < n)), "Other", combined_data[[col_name]])
  
  # Convert column to factor
  combined_data[[col_name]] <- as.factor(combined_data[[col_name]])

  # Add NA as a level if there are any NAs in the column
  if(any(is.na(combined_data[[col_name]]))) {
    combined_data[[col_name]] <- addNA(combined_data[[col_name]])
    
  
  }
}

#Deleting some columns
#rare_level_factors <- sapply(data2, function(x) is.factor(x) && any(table(x) <= 2))
#print(names(data2)[rare_level_factors])


#data$Electrical=as.character(data$Electrical)
#data$Electrical[is.na(data$Electrical)] <- "Other"
#data$Electrical=as.factor(data$Electrical)
#class(combined_data$Electrical)



#data <- data[,-which(names(data) == "Utilities")]


# No more missing values, ordinary variable has been factorized

sum(is.na(combined_data))
#table(data$MiscFeature)
#table(data$Street)
#table(data$Utilities)
#table(data$Condition2)
#table(data$MiscFeature)
#table(data$Electrical)

Checking Colinearity of the model


#Deleting "TotalBsmtSF or X1stFlrSF" , "GarageCars or GarageArea" , "YearBuilt or GarageYearBuilt" , "Fireplaces" or "FireplacesQu" , "GarageCond" or GarageQu",  "PoolQC or PoolArea"

df_numeric <- combined_data[sapply(combined_data, is.numeric)]

# Compute the correlation matrix
cor_matrix <- cor(df_numeric, use = "pairwise.complete.obs")

# Create a correlation plot
corrplot(cor_matrix, type = "upper", order = "hclust", 
         tl.col = "black", tl.srt = 45, tl.cex = 0.5)


# Find pairs with high correlation
high_corr_indices <- findCorrelation(cor_matrix, cutoff = 0.7)

# Get column names from indices
high_corr_names <- colnames(df_numeric)[high_corr_indices]

# Print the column names
print(high_corr_names)

Deleting “TotalBsmtSF or X1stFlrSF” , “GarageCars or GarageArea” , “YearBuilt or GarageYearBuilt” , “Fireplaces” or “FireplacesQu” , “GarageCond” or GarageQual” “PoolQC or PoolArea”, “BsmtFinSF1 or BsmtFinType1”, “BsmtFinSF2 or BsmtFinType2”

Checking for redundency/ deleting noise in the data

Rare Observation provide very little information about the dependent variable and may cause noise in the data set.

table(combined_data$Street)
table(combined_data$Utilities)
table(combined_data$Condition2)
table(combined_data$MiscFeature)

combined_data <- combined_data[, -which(names(combined_data) %in% c('X1stFlrSF', 'GarageCars', 'GarageYrBlt','FireplaceQu','GarageCond','PoolQC','BsmtFinType1','BsmtFinType2' ,'Street', 'Utilities', 'Condition2', 'MiscFeature', 'Alley','Fence'))]


#write.csv(data2,file = 'data2')
#formula(model2)
#colnames(data2[sapply(data2,is.numeric)])
table(combined_data$Foundation)

Checking assumption for regression (full model)

data=combined_data[1:1460,]
data$SalePrice=saleprice
test = combined_data[1461:nrow(combined_data), ]




model = lm(SalePrice ~., data = data)


# residual plots / Histogram / Q-Q plot / Calculate Cook's distances /Create Residuals vs Leverage plot
histogram(model$residuals)
plot(model)



#Look for influential observations

#Looking at observation 1299,524, delete them in the data
data= data[-c(1299,524),]
rownames(data) <- NULL
#write.csv(data,file = "train123")
#colnames(data[sapply(combined_data, is.factor)])

Logging SalePrice to see if it fix the clusterred residuals

data2=data
data2$SalePrice = log(data$SalePrice)
model2 = lm(SalePrice~., data = data2)
#summary(model2)
residualPlot(model2)
#write.csv(data2,file="logdata.csv",row.names = FALSE)

# Compare to model1(unlogged) , the residual plots forms a rather perfect random cloud formation which is ideal
# Histogram
res2= model2$residuals
histogram(res2)

plot(model2)

Perform a forward/backward/stepwise selection in SAS

Dianostics

Build custom regression model in SAS

model_formula= lm(SalePrice ~ MSZoning:GrLivArea+ LotArea:BsmtFinSF1+KitchenAbvGr:GarageQual +GrLivArea:LotArea+ LotArea + OverallQual + OverallCond + YearBuilt  + BsmtExposure + BsmtFinSF1 +BsmtFinSF2 +HeatingQC+BsmtUnfSF + GrLivArea + HalfBath + KitchenAbvGr + KitchenQual + GarageArea + GarageQual + WoodDeckSF +
               ScreenPorch  + MSZoning  + Neighborhood  + BldgType +
               MasVnrType + Foundation + Functional + GarageType  + SaleCondition+Fireplaces,
               data = data2)           

Predition


table(data$MSZoning)
table(test$MSZoning)
levels(test$MSZoning)[is.na(levels(test$MSZoning))] <- "RL"


table(data$Exterior1st )
table(test$Exterior1st )
levels(test$Exterior1st)[is.na(levels(test$Exterior1st))] <- "VinylSd"

table(data$Functional  )
table(test$Functional  )
levels(test$Functional )[is.na(levels(test$Functional ))] <- "Typ"

table(data$SaleType   )
table(test$SaleType   )
levels(test$SaleType  )[is.na(levels(test$SaleType  ))] <- "WD"
#Forward

lm_predict_model= lm(SalePrice ~ MSSubClass + LotArea + OverallQual + OverallCond + YearBuilt + MasVnrArea + ExterQual +
               BsmtQual + BsmtCond + BsmtExposure + BsmtFinSF1 + TotalBsmtSF + GrLivArea + HalfBath +
               BedroomAbvGr + KitchenAbvGr + KitchenQual + GarageArea + GarageQual + WoodDeckSF +
               ScreenPorch + MoSold + MSZoning + LotConfig + Neighborhood + Condition1 + BldgType +
               Exterior1st + MasVnrType + Foundation + Functional + GarageType + PavedDrive + SaleCondition,
               data = data2)
#summary(lm_predict_model)

 
 
prediciton=predict(lm_predict_model,newdata = test)


test$SalePrice=exp(prediciton)
Submission_F=test[,c("Id","SalePrice")]

mean_sale_price <- mean(Submission_F$SalePrice, na.rm = TRUE)
Submission_F$SalePrice[is.na(Submission_F$SalePrice)] <- mean_sale_price

sum(is.na(prediciton))
write.csv(Submission_F, file = 'Submission_F.csv', row.names = FALSE)



plot(lm_predict_model$residuals)
qqPlot(lm_predict_model)
histogram(lm_predict_model$residuals)
plot(lm_predict_model)




#Backward

model_formula <- lm( SalePrice ~ MSSubClass + LotFrontage + LotArea + LandSlope + OverallQual + OverallCond + YearBuilt + MasVnrArea + ExterQual + ExterCond + BsmtQual + BsmtCond + BsmtExposure + BsmtFinSF1 + BsmtFinSF2 + BsmtUnfSF + HeatingQC + X2ndFlrSF + LowQualFinSF + GrLivArea + FullBath + HalfBath + BedroomAbvGr + KitchenAbvGr + KitchenQual + TotRmsAbvGrd + Fireplaces + GarageArea + GarageQual + WoodDeckSF + OpenPorchSF + X3SsnPorch + ScreenPorch + PoolArea + MoSold + MSZoning + LandContour + LotConfig + Neighborhood + Condition1 + BldgType + HouseStyle + RoofMatl + Exterior1st + MasVnrType + Foundation + Functional + GarageType + SaleType + SaleCondition
,data = data2)
#summary(model_formula)
prediciton=predict(model_formula,newdata = test)

test$SalePrice=exp(prediciton)
submission_Backward=test[,c("Id","SalePrice")]

mean_sale_price <- mean(submission_Backward$SalePrice, na.rm = TRUE)
submission_Backward$SalePrice[is.na(submission_Backward$SalePrice)] <- mean_sale_price

sum(is.na(prediciton))
write.csv(submission_Backward, file = 'submission_Backward.csv', row.names = FALSE)


plot(model_formula$residuals)
qqPlot(model_formula)
histogram(model_formula$residuals)
plot(model_formula)

#stepwise

model_formula <- lm(SalePrice ~ MSSubClass + LotFrontage + LotArea + LandSlope + OverallQual + OverallCond + YearBuilt + MasVnrArea + ExterQual + ExterCond + BsmtQual + BsmtCond + BsmtExposure + BsmtFinSF1 + BsmtFinSF2 + TotalBsmtSF + GrLivArea + BedroomAbvGr + KitchenAbvGr + KitchenQual + GarageArea + GarageQual + WoodDeckSF + OpenPorchSF + MoSold + MSZoning + LotConfig + Neighborhood + Condition1 + BldgType + Exterior1st + MasVnrType + Functional + GarageType + PavedDrive + SaleCondition,data = data2)
#summary(model_formula)

prediciton=predict(model_formula,newdata = test)

test$SalePrice=exp(prediciton)
submission_stepwise=test[,c("Id","SalePrice")]

mean_sale_price <- mean(submission_stepwise$SalePrice, na.rm = TRUE)
submission_stepwise$SalePrice[is.na(submission_stepwise$SalePrice)] <- mean_sale_price

sum(is.na(prediciton))
write.csv(submission_stepwise, file = 'submission_stepwise.csv', row.names = FALSE)

plot(model_formula$residuals)
qqPlot(model_formula)
histogram(model_formula$residuals)
plot(model_formula)
#Custom



model_formula= lm(SalePrice ~ MSZoning:GrLivArea+ LotArea:BsmtFinSF1+KitchenAbvGr:GarageQual +GrLivArea:LotArea+ LotArea + OverallQual + OverallCond + YearBuilt  + BsmtExposure + BsmtFinSF1 +BsmtFinSF2 +HeatingQC+BsmtUnfSF + GrLivArea + HalfBath + KitchenAbvGr + KitchenQual + GarageArea + GarageQual + WoodDeckSF +
               ScreenPorch  + MSZoning  + Neighborhood  + BldgType +
               MasVnrType + Foundation + Functional + GarageType  + SaleCondition+Fireplaces,
               data = data2)           
#summary(model_formula)

 
prediciton=predict(model_formula,newdata = test)  

test$SalePrice=exp(prediciton)
submission_Cust=test[,c("Id","SalePrice")]

mean_sale_price <- mean(submission_Cust$SalePrice, na.rm = TRUE)
submission_Cust$SalePrice[is.na(submission_Cust$SalePrice)] <- mean_sale_price

sum(is.na(prediciton))
write.csv(submission_Cust, file = 'submission_Cust.csv', row.names = FALSE)

plot(model_formula)
plot(model_formula$residuals)
histogram(model_formula$residuals)


#trial2

model_formula= lm(SalePrice ~ (YearBuilt:ScreenPorch+LotArea:TotalBsmtSF+KitchenAbvGr:GarageQual +GrLivArea:LotArea+ LotArea + OverallQual + OverallCond + YearBuilt  + BsmtExposure + BsmtFinSF1 +BsmtFinSF2 +HeatingQC+BsmtUnfSF + GrLivArea + HalfBath + KitchenAbvGr + KitchenQual + GarageArea + GarageQual + WoodDeckSF +
               ScreenPorch  + MSZoning  + Neighborhood  + BldgType +
               MasVnrType + Foundation + Functional + GarageType  + SaleCondition+Fireplaces)^2,
               data = data2)  
#summary(model_formula)

prediciton=predict(model_formula,newdata = test)  

test$SalePrice=exp(prediciton)
submission_Cust=test[,c("Id","SalePrice")]

mean_sale_price <- mean(submission_Cust$SalePrice, na.rm = TRUE)
submission_Cust$SalePrice[is.na(submission_Cust$SalePrice)] <- mean_sale_price

sum(is.na(prediciton))
write.csv(submission_Cust, file = 'submission_Cust.csv', row.names = FALSE)

Examen relationship in Sales price in neighborhood ‘NAmes’, ‘Edwards’, ‘BrkSide’

options(scipen = 999)
library(dplyr)
library(ggplot2)

data= read.csv("https://raw.githubusercontent.com/anishkapeter/Stat1Project/main/train.csv")

# Model without Interaction Variable 
filtered_neighborhood = data %>% filter (Neighborhood %in% c('NAmes', 'Edwards', 'BrkSide'))

filtered_neighborhood_model= lm(SalePrice ~ GrLivArea, data = filtered_neighborhood)
#summary(filtered_neighborhood_model)

# Check Assumptions Model Without Indicator and Interaction Variable  
plot(filtered_neighborhood_model)

histogram(filtered_neighborhood_model$residuals)

ggplot(filtered_neighborhood,aes(x =GrLivArea , y =SalePrice )) + 
  geom_point() +
  ggtitle("ScatterPlot of SalePrice vs GrLivArea") 

# Residual plot clustered, using log-log method to transform the dataset

# Log log Transform to data 
data3=data
data3$SalePrice = log(data$SalePrice)
data3$GrLivArea = log(data$GrLivArea)

# filter the logged data to only include the 3 neighborhoods of interest
filtered_data2 <- data3 %>% filter(Neighborhood %in% c('NAmes', 'Edwards', 'BrkSide'))

# build model on log data without interaction and indicator var
filtered_data2_model = lm(SalePrice ~ GrLivArea, data = filtered_data2)
#summary(filtered_data2_model)

# Checking Assumptions 
ggplot(filtered_data2,aes(x =GrLivArea , y =SalePrice )) +
  geom_point()+ggtitle("ScatterPlot of Log(SalePrice) vs Log(GrLivArea)") + 
  xlab("Log(GrLivArea)") +
  ylab("Log(SalePrice)")

hist(filtered_data2_model$residuals)

plot(filtered_data2_model)


# Confidence Interval for Log Model without Interaction or Indicator
confint(filtered_data2_model)

plot(filtered_data2$GrLivArea, filtered_data2$SalePrice, 
     main="Scatterplot with Regression Line", 
     xlab="Above grade (ground) living area square feet (GrLivArea)", 
     ylab="Sale Price (SalePrice)", pch=19, frame=FALSE, col="blue")+
  abline(filtered_data2_model, col="red")

Therefore the regression model predicting SalePrice using GrlivArea is

SalePrice = 7.58437 + 0.59230 * GrlivArea

Adding Indicator Variable

# Adding Indicator Variable 
filtered_data2_model3 <- lm(SalePrice ~  GrLivArea + Neighborhood, data = filtered_data2)
#summary(filtered_data2_model3)

Adding interaction variables


# Fit the model
filtered_data2_model2 <- lm(SalePrice ~  GrLivArea + GrLivArea * Neighborhood, data = filtered_data2)

# Summary of the model
#summary(filtered_data2_model2)

# Confidence intervals
confint(filtered_data2_model2)


# Residuals histogram
histogram <- ggplot(filtered_data2_model2, aes(x=residuals)) +
  geom_histogram(binwidth=1, color="black", fill="white") +
  theme_minimal() +
  labs(x="Residuals", y="Frequency", title="Histogram of Residuals")

# Model diagnostics
plot_diag <- plot(filtered_data2_model2, diagnostic = TRUE)


# Model Coefficients
model_coef <- coef(filtered_data2_model2)

Anova Analysis

#ANOVA for model with Neighborhood as Interaction Variable 
anova(filtered_data2_model3)

#ANOVA for model with Neighborhood as Indicator Variable 
anova(filtered_data2_model2)

#ANOVA for model without Neighborhood  
anova(filtered_data2_model)

1 - pf(68.02972973,2,377)

1 - pf(8.641891892,2,377)

Model with Interaction Summaries

For our best performing model we had #1288 on Kaggle, Yah! Dianostics

For each neighborhood, the regression model predicting SalePrice using GrLivArea is given by:

Neighborhood ‘BrkSide’:

logSalePrice = 5.91292 + 0.81965*logGrLivArea

Interpretation of the Coefficients

Every time the square footage of the living area doubles, there is an estimated multiplicative increase of 1.76497775436 (about 76.5% increase) in the median Sale Price.

When the square footage of the living area is 0, the estimated median SalePrice 369.78435.

Interpretation of Confidence Intervals

Every time the square footage of the living area doubles, the estimated multiplicative increase in median Sales Price for Brookeside is between 1.60081478829 and 1.94597031156.

When the square footage of the living area is 0., the estimated median Sale Price is between 137.10639085 and 997.332584908 in Brookside neighborhood.

Neighborhood ‘NAmes’:

logSalePrice = 7.74784 + 0.47303*logGrLivArea

Interpretation of the Coefficients

Every time the square footage of the living area doubles, there is an estimated multiplicative increase of 1.38802158181, (about 38.8% increase) in the median Sale Price.

When the square footage of the living area is 0, the estimated median SalePrice 4879.16803655.

Interpretation of Confidence Intervals

When the square footage of the living area is 0, the estimated median SalePrice 4879.16803655 .

When the square footage of the living area is 0, the estimated median Sale Price is between 556.146417272 and 42805.5779923 in North Ames neighborhood.

Neighborhood ‘Edwards’:

logSalePrice = 8.00651 + 0.51967 *logGrLivArea

Interpretation of the Coefficients

Every time the square footage of the living area doubles, there is an estimated multiplicative increase of 1.4336074105 (about 43.36% increase) in the median Sale Price.

When the square footage of the living area is 0, the estimated median Sale Price 3000.42732748.

Confidence Intervals and Interpretation

When the square footage of the living area is 0, the estimated median Sale Price is between 312.416333335 and 28815.756004 for houses in the Edwards Neighborhood.

Every time the square footage of the living area doubles, the estimated multiplicative increase in median Sales Price for Edwards Neighborhood is between 1.14827731299 and 1.78988066094.

filtered_data2 library(ggplot2) filtered_neighborhood %>% filter(Neighborhood == “BrkSide”) %>% ggplot(aes(x=GrLivArea, y = SalePrice)) + geom_point( color = “steelblue”) + ggtitle(“Sale Price vs Living Area Sq.Ft in Brookside”) + xlab(“Square Footage of Living Area”) + ylab(“Sales Price in Dollars”)

filtered_neighborhood %>% filter(Neighborhood == “Edwards”) %>% ggplot(aes(x=GrLivArea, y = SalePrice)) + geom_point( color = “steelblue”) + ggtitle(“Sale Price vs Living Area Sq.Ft in Edwards”) + xlab(“Square Footage of Living Area”) + ylab(“Sales Price in Dollars”)

filtered_neighborhood %>% filter(Neighborhood == “NAmes”) %>% ggplot(aes(x=GrLivArea, y = SalePrice)) + geom_point(color = “steelblue”) + ggtitle(“Sale Price vs Living Area Sq.Ft in North Ames”) + xlab(“Square Footage of Living Area”) + ylab(“Sales Price in Dollars”)

LS0tDQp0aXRsZTogIkhvdXNlUHJpY2UgUHJlZGljdGlvbiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQpkYXRlOiAiMjAyMy0wNy0zMCINCi0tLQ0KDQotLS0NCg0KIyBMb2FkIG5lY2Vzc2FyeSBwYWNrYWdlcywgbG9hZCBkYXRhLg0KDQpgYGB7Uix3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KI2xvYWQgbmVjZXNzYXJ5IHBhY2thZ2VzOg0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KG11bHRpVVMpDQpsaWJyYXJ5KGJvb3QpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShvbHNycikNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkoY2FyKQ0KDQoNCiNMb2FkIERhdGENCg0KZGF0YT1yZWFkLmNzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2FuaXNoa2FwZXRlci9TdGF0MVByb2plY3QvbWFpbi90cmFpbi5jc3YnKQ0KDQpgYGANCiMgRmlsbCBtaXNzaW5nIHZhbHVlcyBpbiBudW1lcmljIGNvbHVtbnMgd2l0aCBLTk4gaW1wdXRhdGlvbg0KYGBge3Isd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCm51bWVyaWNfY29scyA8LSBuYW1lcyhkYXRhKVtzYXBwbHkoZGF0YSwgaXMubnVtZXJpYyldDQojY29sU3Vtcyhpcy5uYShkYXRhWyxudW1lcmljX2NvbHNdKSkNCiNtb2RlKGRhdGEkTG90RnJvbnRhZ2UpDQoNCg0KY2F0ZWdvcmljYWxfY29scyA8LSBuYW1lcyhkYXRhKVtzYXBwbHkoZGF0YSwgaXMuY2hhcmFjdGVyKV0NCiNsZW5ndGgoY2F0ZWdvcmljYWxfY29scykrbGVuZ3RoKG51bWVyaWNfY29scykNCm51bWVyaWNfZGF0YSA8LSBkYXRhWywgbnVtZXJpY19jb2xzXQ0KbnVtZXJpY19kYXRhX2ltcHV0ZWQgPC0gS05OaW1wKGFzLm1hdHJpeChudW1lcmljX2RhdGEpKSAgIyBjb252ZXJ0IGRhdGEgZnJhbWUgdG8gbWF0cml4IGZvciBrbm5JbXB1dGUNCmRhdGFbbnVtZXJpY19jb2xzXSA8LSBudW1lcmljX2RhdGFfaW1wdXRlZA0KDQpgYGANCg0KDQojIGNvbWJpbmUgdHJhaW5pbmcgYW5kIHRlc3QgZGF0YSB0b2dldGhlciwgZm9yIGVhc2llciBjbGVhbmluZw0KDQpgYGB7cn0NCnVybCA8LSAiaHR0cHM6Ly9naXRodWIuY29tL2FuaXNoa2FwZXRlci9TdGF0MVByb2plY3QvYmxvYi9tYWluL3Rlc3QuY3N2P3Jhdz10cnVlIg0KdGVzdCA8LSByZWFkLmNzdih1cmwpDQoNCmRhdGFfYyA8LSBzdWJzZXQoZGF0YSwgc2VsZWN0ID0gLWMoU2FsZVByaWNlKSkNCnNhbGVwcmljZSA9IGRhdGEkU2FsZVByaWNlDQojIENvbWJpbmUgdGhlIGRhdGEgYW5kIHRlc3QgZGF0YWZyYW1lcw0KY29tYmluZWRfZGF0YSA8LSByYmluZChkYXRhX2MsIHRlc3QpDQoNCg0KDQpgYGANCg0KIyBEZWZpbmUgb3JkaW5hbCBjb2x1bW5zLCByZWdyb3VwIGNoYXJhY3RlciBjb2x1bW5zIGFuZCBhcHBseSBmYWN0b3IgZW5jb2RpbmcuDQpgYGB7cix3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyBJZGVudGlmeSBjaGFyYWN0ZXIgY29sdW1ucw0KDQoNCg0KY29tYmluZWRfZGF0YSRFeHRlckNvbmQgPC0gZmFjdG9yKGNvbWJpbmVkX2RhdGEkRXh0ZXJDb25kLCBsZXZlbHMgPSBjKCJQbyIsICJGYSIsICJUQSIsICJHZCIsICJFeCIpKQ0KY29tYmluZWRfZGF0YSRFeHRlckNvbmQgPC0gYXMubnVtZXJpYyhjb21iaW5lZF9kYXRhJEV4dGVyQ29uZCkNCmNvbWJpbmVkX2RhdGEkRXh0ZXJRdWFsIDwtIGZhY3Rvcihjb21iaW5lZF9kYXRhJEV4dGVyUXVhbCwgbGV2ZWxzID0gYygiRmEiLCAiVEEiLCAiR2QiLCAiRXgiKSkNCmNvbWJpbmVkX2RhdGEkRXh0ZXJRdWFsIDwtIGFzLm51bWVyaWMoY29tYmluZWRfZGF0YSRFeHRlclF1YWwpDQoNCg0KIyBGaXJzdCwgZW5zdXJlIE5BIHZhbHVlcyBhcmUgbm90IHRyZWF0ZWQgYXMgbWlzc2luZyBkYXRhDQpjb21iaW5lZF9kYXRhJEJzbXRRdWFsIDwtIGFkZE5BKGNvbWJpbmVkX2RhdGEkQnNtdFF1YWwpDQpjb21iaW5lZF9kYXRhJEJzbXRDb25kIDwtIGFkZE5BKGNvbWJpbmVkX2RhdGEkQnNtdENvbmQpDQpjb21iaW5lZF9kYXRhJEJzbXRRdWFsIDwtIGZhY3Rvcihjb21iaW5lZF9kYXRhJEJzbXRRdWFsLCBsZXZlbHMgPSBjKCJQbyIsICJGYSIsICJUQSIsICJHZCIsICJFeCIpKQ0KY29tYmluZWRfZGF0YSRCc210Q29uZCA8LSBmYWN0b3IoY29tYmluZWRfZGF0YSRCc210Q29uZCwgbGV2ZWxzID0gYygiUG8iLCAiRmEiLCAiVEEiLCAiR2QiLCAiRXgiKSkNCmNvbWJpbmVkX2RhdGEkQnNtdFF1YWwgPC0gYXMubnVtZXJpYyhjb21iaW5lZF9kYXRhJEJzbXRRdWFsKQ0KY29tYmluZWRfZGF0YSRCc210Q29uZCA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkQnNtdENvbmQpDQoNCg0KDQojIEZpcnN0LCBlbnN1cmUgTkEgdmFsdWVzIGFyZSBub3QgdHJlYXRlZCBhcyBtaXNzaW5nIGRhdGENCmNvbWJpbmVkX2RhdGEkR2FyYWdlQ29uZCA8LSBhZGROQShjb21iaW5lZF9kYXRhJEdhcmFnZUNvbmQpDQpjb21iaW5lZF9kYXRhJEdhcmFnZVF1YWwgPC0gYWRkTkEoY29tYmluZWRfZGF0YSRHYXJhZ2VRdWFsKQ0KY29tYmluZWRfZGF0YSRHYXJhZ2VDb25kIDwtIGZhY3Rvcihjb21iaW5lZF9kYXRhJEdhcmFnZUNvbmQsIGxldmVscyA9IGMoIlBvIiwgIkZhIiwgIlRBIiwgIkdkIiwgIkV4IikpDQpjb21iaW5lZF9kYXRhJEdhcmFnZVF1YWwgPC0gZmFjdG9yKGNvbWJpbmVkX2RhdGEkR2FyYWdlUXVhbCwgbGV2ZWxzID0gYygiUG8iLCAiRmEiLCAiVEEiLCAiR2QiLCAiRXgiKSkNCmNvbWJpbmVkX2RhdGEkR2FyYWdlQ29uZCA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkR2FyYWdlQ29uZCkNCmNvbWJpbmVkX2RhdGEkR2FyYWdlUXVhbCA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkR2FyYWdlUXVhbCkNCg0KDQoNCiMgQ29udmVydCBOQSB2YWx1ZXMgdG8gZmFjdG9yIGxldmVscw0KY29tYmluZWRfZGF0YSRQb29sUUMgPC0gYWRkTkEoY29tYmluZWRfZGF0YSRQb29sUUMpDQpjb21iaW5lZF9kYXRhJEZpcmVwbGFjZVF1IDwtIGFkZE5BKGNvbWJpbmVkX2RhdGEkRmlyZXBsYWNlUXUpDQpjb21iaW5lZF9kYXRhJEhlYXRpbmdRQyA8LSBhZGROQShjb21iaW5lZF9kYXRhJEhlYXRpbmdRQykNCmNvbWJpbmVkX2RhdGEkS2l0Y2hlblF1YWwgPC0gYWRkTkEoY29tYmluZWRfZGF0YSRLaXRjaGVuUXVhbCkNCmNvbWJpbmVkX2RhdGEkQnNtdEV4cG9zdXJlIDwtIGFkZE5BKGNvbWJpbmVkX2RhdGEkQnNtdEV4cG9zdXJlKQ0KY29tYmluZWRfZGF0YSRQb29sUUMgPC0gZmFjdG9yKGNvbWJpbmVkX2RhdGEkUG9vbFFDLCBsZXZlbHMgPSBjKCJQbyIsICJGYSIsICJUQSIsICJHZCIsICJFeCIpKQ0KY29tYmluZWRfZGF0YSRGaXJlcGxhY2VRdSA8LSBmYWN0b3IoY29tYmluZWRfZGF0YSRGaXJlcGxhY2VRdSwgbGV2ZWxzID0gYygiUG8iLCAiRmEiLCAiVEEiLCAiR2QiLCAiRXgiKSkNCmNvbWJpbmVkX2RhdGEkSGVhdGluZ1FDIDwtIGZhY3Rvcihjb21iaW5lZF9kYXRhJEhlYXRpbmdRQywgbGV2ZWxzID0gYygiUG8iLCAiRmEiLCAiVEEiLCAiR2QiLCAiRXgiKSkNCmNvbWJpbmVkX2RhdGEkS2l0Y2hlblF1YWwgPC0gZmFjdG9yKGNvbWJpbmVkX2RhdGEkS2l0Y2hlblF1YWwsIGxldmVscyA9IGMoIlBvIiwgIkZhIiwgIlRBIiwgIkdkIiwgIkV4IikpDQpjb21iaW5lZF9kYXRhJEJzbXRFeHBvc3VyZSA8LSBmYWN0b3IoY29tYmluZWRfZGF0YSRCc210RXhwb3N1cmUsIGxldmVscyA9IGMoIk5vIiwgIk1uIiwgIkF2IiwgIkdkIikpDQpjb21iaW5lZF9kYXRhJFBvb2xRQyA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkUG9vbFFDKQ0KY29tYmluZWRfZGF0YSRGaXJlcGxhY2VRdSA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkRmlyZXBsYWNlUXUpDQpjb21iaW5lZF9kYXRhJEhlYXRpbmdRQyA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkSGVhdGluZ1FDKQ0KY29tYmluZWRfZGF0YSRLaXRjaGVuUXVhbCA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkS2l0Y2hlblF1YWwpDQpjb21iaW5lZF9kYXRhJEJzbXRFeHBvc3VyZSA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkQnNtdEV4cG9zdXJlKQ0KDQoNCg0KIyBDb252ZXJ0IE5BIHZhbHVlcyB0byBmYWN0b3IgbGV2ZWxzDQpjb21iaW5lZF9kYXRhJEJzbXRGaW5UeXBlMSA8LSBhZGROQShjb21iaW5lZF9kYXRhJEJzbXRGaW5UeXBlMSkNCmNvbWJpbmVkX2RhdGEkQnNtdEZpblR5cGUyIDwtIGFkZE5BKGNvbWJpbmVkX2RhdGEkQnNtdEZpblR5cGUyKQ0KY29tYmluZWRfZGF0YSRGZW5jZSA8LSBhZGROQShjb21iaW5lZF9kYXRhJEZlbmNlKQ0KY29tYmluZWRfZGF0YSRHYXJhZ2VGaW5pc2ggPC0gYWRkTkEoY29tYmluZWRfZGF0YSRHYXJhZ2VGaW5pc2gpDQpjb21iaW5lZF9kYXRhJEFsbGV5IDwtIGFkZE5BKGNvbWJpbmVkX2RhdGEkQWxsZXkpDQoNCiN0YWJsZShjb21iaW5lZF9kYXRhJEFsbGV5KQ0KDQpjb21iaW5lZF9kYXRhJEJzbXRGaW5UeXBlMSA8LSBmYWN0b3IoY29tYmluZWRfZGF0YSRCc210RmluVHlwZTEsIGxldmVscyA9IGMoIlVuZiIsICJMd1EiLCAiUmVjIiwgIkJMUSIsICJBTFEiLCAiR0xRIikpDQpjb21iaW5lZF9kYXRhJEJzbXRGaW5UeXBlMiA8LSBmYWN0b3IoY29tYmluZWRfZGF0YSRCc210RmluVHlwZTIsIGxldmVscyA9IGMoIlVuZiIsICJMd1EiLCAiUmVjIiwgIkJMUSIsICJBTFEiLCAiR0xRIikpDQpjb21iaW5lZF9kYXRhJENlbnRyYWxBaXIgPC0gZmFjdG9yKGNvbWJpbmVkX2RhdGEkQ2VudHJhbEFpciwgbGV2ZWxzID0gYygiTiIsICJZIikpDQpjb21iaW5lZF9kYXRhJEZlbmNlIDwtIGZhY3Rvcihjb21iaW5lZF9kYXRhJEZlbmNlLCBsZXZlbHMgPSBjKCJNbld3IiwgIkdkV28iLCAiTW5QcnYiLCAiR2RQcnYiKSkNCmNvbWJpbmVkX2RhdGEkR2FyYWdlRmluaXNoIDwtIGZhY3Rvcihjb21iaW5lZF9kYXRhJEdhcmFnZUZpbmlzaCwgbGV2ZWxzID0gYygiVW5mIiwgIlJGbiIsICJGaW4iKSkNCmNvbWJpbmVkX2RhdGEkQWxsZXkgPC0gZmFjdG9yKGNvbWJpbmVkX2RhdGEkQWxsZXksIGxldmVscyA9IGMoIkdydmwiLCAiUGF2ZSIpKQ0KY29tYmluZWRfZGF0YSRMb3RTaGFwZSA8LSBmYWN0b3IoY29tYmluZWRfZGF0YSRMb3RTaGFwZSwgbGV2ZWxzID0gYygiUmVnIiwgIklSMSIsICJJUjIiLCAiSVIzIikpDQpjb21iaW5lZF9kYXRhJExhbmRTbG9wZSA8LSBmYWN0b3IoY29tYmluZWRfZGF0YSRMYW5kU2xvcGUsIGxldmVscyA9IGMoIkd0bCIsICJNb2QiLCAiU2V2IikpDQoNCmNvbWJpbmVkX2RhdGEkQnNtdEZpblR5cGUxIDwtIGFzLm51bWVyaWMoY29tYmluZWRfZGF0YSRCc210RmluVHlwZTEpDQpjb21iaW5lZF9kYXRhJEJzbXRGaW5UeXBlMiA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkQnNtdEZpblR5cGUyKQ0KY29tYmluZWRfZGF0YSRDZW50cmFsQWlyIDwtIGFzLm51bWVyaWMoY29tYmluZWRfZGF0YSRDZW50cmFsQWlyKQ0KY29tYmluZWRfZGF0YSRGZW5jZSA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkRmVuY2UpDQpjb21iaW5lZF9kYXRhJEdhcmFnZUZpbmlzaCA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkR2FyYWdlRmluaXNoKQ0KY29tYmluZWRfZGF0YSRBbGxleSA8LSBhcy5udW1lcmljKGNvbWJpbmVkX2RhdGEkQWxsZXkpDQpjb21iaW5lZF9kYXRhJExvdFNoYXBlIDwtIGFzLm51bWVyaWMoY29tYmluZWRfZGF0YSRMb3RTaGFwZSkNCmNvbWJpbmVkX2RhdGEkTGFuZFNsb3BlIDwtIGFzLm51bWVyaWMoY29tYmluZWRfZGF0YSRMYW5kU2xvcGUpDQoNCg0KDQoNCm9yZGluYWxfY29scyA8LSBjKCdFeHRlclF1YWwnLCAnRXh0ZXJDb25kJywgJ0JzbXRRdWFsJywgJ0JzbXRDb25kJywgDQogICAgICAgICAgICAgICAgICAnR2FyYWdlQ29uZCcsICdHYXJhZ2VRdWFsJywgJ1Bvb2xRQycsICdGaXJlcGxhY2VRdScsIA0KICAgICAgICAgICAgICAgICAgJ0hlYXRpbmdRQycsICdLaXRjaGVuUXVhbCcsICdCc210RXhwb3N1cmUnLCAnQnNtdEZpblR5cGUxJywgDQogICAgICAgICAgICAgICAgJ0JzbXRGaW5UeXBlMicsICdDZW50cmFsQWlyJywgJ0ZlbmNlJywnR2FyYWdlRmluaXNoJywnQWxsZXknLCdMb3RTaGFwZScsJ0xhbmRTbG9wZScpDQoNCiN0YWJsZShkYXRhJEV4dGVyUXVhbCkNCg0KDQpjb21iaW5lZF9kYXRhW29yZGluYWxfY29sc10gPC0gbGFwcGx5KGNvbWJpbmVkX2RhdGFbb3JkaW5hbF9jb2xzXSwgZnVuY3Rpb24oeCkgcmVwbGFjZSh4LCBpcy5uYSh4KSwgMCkpDQoNCg0KDQoNCg0KIyBUcmFuc2Zvcm0gb3JkaW5hbCBjb2x1bW5zIGludG8gZmFjdG9ycyBhbmQgcmVwbGFjZSBOQSB3aXRoIDANCg0KI2RhdGFbb3JkaW5hbF9jb2xzXSA8LSBsYXBwbHkoZGF0YVtvcmRpbmFsX2NvbHNdLCBmdW5jdGlvbih4KSB7DQojICB4IDwtIGFzLmZhY3Rvcih4KQ0KIyAgbGV2ZWxzKHgpIDwtIGMobGV2ZWxzKHgpLCAiMCIpDQojIHhbaXMubmEoeCldIDwtICIwIg0KIyAgcmV0dXJuKHgpDQojIH0pDQoNCiMgQ2hlY2tpbmcgYWxsIGNoYXJhY3RlciBjb2x1bW5zDQojY29sbmFtZXMoZGF0YSlbY29sU3Vtcyhpcy5uYShkYXRhKSkgPiAwXQ0KDQoNCg0KDQojIFRocmVzaG9sZCBmb3IgJ3JhcmUnIG9ic2VydmF0aW9ucw0KbiA8LSAxMCANCg0KIyBMb29wIHRocm91Z2ggdGhlIGNoYXJhY3RlciBjb2x1bW5zDQpmb3IgKGNvbF9uYW1lIGluIGNvbG5hbWVzKGNvbWJpbmVkX2RhdGEpW3NhcHBseShjb21iaW5lZF9kYXRhLCBpcy5jaGFyYWN0ZXIpXSkgew0KICAjIENvbnZlcnQgcmFyZSBvYnNlcnZhdGlvbnMgdG8gJ090aGVyJw0KICBjb21iaW5lZF9kYXRhW1tjb2xfbmFtZV1dIDwtIGlmZWxzZShjb21iaW5lZF9kYXRhW1tjb2xfbmFtZV1dICVpbiUgbmFtZXMod2hpY2godGFibGUoY29tYmluZWRfZGF0YVtbY29sX25hbWVdXSkgPCBuKSksICJPdGhlciIsIGNvbWJpbmVkX2RhdGFbW2NvbF9uYW1lXV0pDQogIA0KICAjIENvbnZlcnQgY29sdW1uIHRvIGZhY3Rvcg0KICBjb21iaW5lZF9kYXRhW1tjb2xfbmFtZV1dIDwtIGFzLmZhY3Rvcihjb21iaW5lZF9kYXRhW1tjb2xfbmFtZV1dKQ0KDQogICMgQWRkIE5BIGFzIGEgbGV2ZWwgaWYgdGhlcmUgYXJlIGFueSBOQXMgaW4gdGhlIGNvbHVtbg0KICBpZihhbnkoaXMubmEoY29tYmluZWRfZGF0YVtbY29sX25hbWVdXSkpKSB7DQogICAgY29tYmluZWRfZGF0YVtbY29sX25hbWVdXSA8LSBhZGROQShjb21iaW5lZF9kYXRhW1tjb2xfbmFtZV1dKQ0KICAgIA0KICANCiAgfQ0KfQ0KDQojRGVsZXRpbmcgc29tZSBjb2x1bW5zDQojcmFyZV9sZXZlbF9mYWN0b3JzIDwtIHNhcHBseShkYXRhMiwgZnVuY3Rpb24oeCkgaXMuZmFjdG9yKHgpICYmIGFueSh0YWJsZSh4KSA8PSAyKSkNCiNwcmludChuYW1lcyhkYXRhMilbcmFyZV9sZXZlbF9mYWN0b3JzXSkNCg0KDQojZGF0YSRFbGVjdHJpY2FsPWFzLmNoYXJhY3RlcihkYXRhJEVsZWN0cmljYWwpDQojZGF0YSRFbGVjdHJpY2FsW2lzLm5hKGRhdGEkRWxlY3RyaWNhbCldIDwtICJPdGhlciINCiNkYXRhJEVsZWN0cmljYWw9YXMuZmFjdG9yKGRhdGEkRWxlY3RyaWNhbCkNCiNjbGFzcyhjb21iaW5lZF9kYXRhJEVsZWN0cmljYWwpDQoNCg0KDQojZGF0YSA8LSBkYXRhWywtd2hpY2gobmFtZXMoZGF0YSkgPT0gIlV0aWxpdGllcyIpXQ0KDQoNCiMgTm8gbW9yZSBtaXNzaW5nIHZhbHVlcywgb3JkaW5hcnkgdmFyaWFibGUgaGFzIGJlZW4gZmFjdG9yaXplZA0KDQpzdW0oaXMubmEoY29tYmluZWRfZGF0YSkpDQojdGFibGUoZGF0YSRNaXNjRmVhdHVyZSkNCiN0YWJsZShkYXRhJFN0cmVldCkNCiN0YWJsZShkYXRhJFV0aWxpdGllcykNCiN0YWJsZShkYXRhJENvbmRpdGlvbjIpDQojdGFibGUoZGF0YSRNaXNjRmVhdHVyZSkNCiN0YWJsZShkYXRhJEVsZWN0cmljYWwpDQoNCg0KDQoNCg0KDQpgYGANCg0KDQoNCg0KDQojIENoZWNraW5nIENvbGluZWFyaXR5IG9mIHRoZSBtb2RlbA0KDQpgYGB7cn0NCg0KI0RlbGV0aW5nICJUb3RhbEJzbXRTRiBvciBYMXN0RmxyU0YiICwgIkdhcmFnZUNhcnMgb3IgR2FyYWdlQXJlYSIgLCAiWWVhckJ1aWx0IG9yIEdhcmFnZVllYXJCdWlsdCIgLCAiRmlyZXBsYWNlcyIgb3IgIkZpcmVwbGFjZXNRdSIgLCAiR2FyYWdlQ29uZCIgb3IgR2FyYWdlUXUiLCAgIlBvb2xRQyBvciBQb29sQXJlYSINCg0KZGZfbnVtZXJpYyA8LSBjb21iaW5lZF9kYXRhW3NhcHBseShjb21iaW5lZF9kYXRhLCBpcy5udW1lcmljKV0NCg0KIyBDb21wdXRlIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXgNCmNvcl9tYXRyaXggPC0gY29yKGRmX251bWVyaWMsIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQ0KDQojIENyZWF0ZSBhIGNvcnJlbGF0aW9uIHBsb3QNCmNvcnJwbG90KGNvcl9tYXRyaXgsIHR5cGUgPSAidXBwZXIiLCBvcmRlciA9ICJoY2x1c3QiLCANCiAgICAgICAgIHRsLmNvbCA9ICJibGFjayIsIHRsLnNydCA9IDQ1LCB0bC5jZXggPSAwLjUpDQoNCg0KIyBGaW5kIHBhaXJzIHdpdGggaGlnaCBjb3JyZWxhdGlvbg0KaGlnaF9jb3JyX2luZGljZXMgPC0gZmluZENvcnJlbGF0aW9uKGNvcl9tYXRyaXgsIGN1dG9mZiA9IDAuNykNCg0KIyBHZXQgY29sdW1uIG5hbWVzIGZyb20gaW5kaWNlcw0KaGlnaF9jb3JyX25hbWVzIDwtIGNvbG5hbWVzKGRmX251bWVyaWMpW2hpZ2hfY29ycl9pbmRpY2VzXQ0KDQojIFByaW50IHRoZSBjb2x1bW4gbmFtZXMNCnByaW50KGhpZ2hfY29ycl9uYW1lcykNCmBgYA0KRGVsZXRpbmcgIlRvdGFsQnNtdFNGIG9yIFgxc3RGbHJTRiIgLCAiR2FyYWdlQ2FycyBvciBHYXJhZ2VBcmVhIiAsICJZZWFyQnVpbHQgb3IgR2FyYWdlWWVhckJ1aWx0IiAsICJGaXJlcGxhY2VzIiBvciAiRmlyZXBsYWNlc1F1IiAsICJHYXJhZ2VDb25kIiBvciBHYXJhZ2VRdWFsIiAiUG9vbFFDIG9yIFBvb2xBcmVhIiwgIkJzbXRGaW5TRjEgb3IgQnNtdEZpblR5cGUxIu+8jCDigJxCc210RmluU0YyIG9yIEJzbXRGaW5UeXBlMiIgDQoNCiMgQ2hlY2tpbmcgZm9yIHJlZHVuZGVuY3kvIGRlbGV0aW5nIG5vaXNlIGluIHRoZSBkYXRhDQoNClJhcmUgT2JzZXJ2YXRpb24gcHJvdmlkZSB2ZXJ5IGxpdHRsZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGFuZCBtYXkgY2F1c2Ugbm9pc2UgaW4gdGhlIGRhdGEgc2V0Lg0KDQpgYGB7cn0NCnRhYmxlKGNvbWJpbmVkX2RhdGEkU3RyZWV0KQ0KdGFibGUoY29tYmluZWRfZGF0YSRVdGlsaXRpZXMpDQp0YWJsZShjb21iaW5lZF9kYXRhJENvbmRpdGlvbjIpDQp0YWJsZShjb21iaW5lZF9kYXRhJE1pc2NGZWF0dXJlKQ0KDQpjb21iaW5lZF9kYXRhIDwtIGNvbWJpbmVkX2RhdGFbLCAtd2hpY2gobmFtZXMoY29tYmluZWRfZGF0YSkgJWluJSBjKCdYMXN0RmxyU0YnLCAnR2FyYWdlQ2FycycsICdHYXJhZ2VZckJsdCcsJ0ZpcmVwbGFjZVF1JywnR2FyYWdlQ29uZCcsJ1Bvb2xRQycsJ0JzbXRGaW5UeXBlMScsJ0JzbXRGaW5UeXBlMicgLCdTdHJlZXQnLCAnVXRpbGl0aWVzJywgJ0NvbmRpdGlvbjInLCAnTWlzY0ZlYXR1cmUnLCAnQWxsZXknLCdGZW5jZScpKV0NCg0KDQojd3JpdGUuY3N2KGRhdGEyLGZpbGUgPSAnZGF0YTInKQ0KI2Zvcm11bGEobW9kZWwyKQ0KI2NvbG5hbWVzKGRhdGEyW3NhcHBseShkYXRhMixpcy5udW1lcmljKV0pDQp0YWJsZShjb21iaW5lZF9kYXRhJEZvdW5kYXRpb24pDQpgYGANCg0KDQojIENoZWNraW5nIGFzc3VtcHRpb24gZm9yIHJlZ3Jlc3Npb24gKGZ1bGwgbW9kZWwpDQoNCmBgYHtyLHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpkYXRhPWNvbWJpbmVkX2RhdGFbMToxNDYwLF0NCmRhdGEkU2FsZVByaWNlPXNhbGVwcmljZQ0KdGVzdCA9IGNvbWJpbmVkX2RhdGFbMTQ2MTpucm93KGNvbWJpbmVkX2RhdGEpLCBdDQoNCg0KDQoNCm1vZGVsID0gbG0oU2FsZVByaWNlIH4uLCBkYXRhID0gZGF0YSkNCg0KDQojIHJlc2lkdWFsIHBsb3RzIC8gSGlzdG9ncmFtIC8gUS1RIHBsb3QgLyBDYWxjdWxhdGUgQ29vaydzIGRpc3RhbmNlcyAvQ3JlYXRlIFJlc2lkdWFscyB2cyBMZXZlcmFnZSBwbG90DQpoaXN0b2dyYW0obW9kZWwkcmVzaWR1YWxzKQ0KcGxvdChtb2RlbCkNCg0KDQoNCiNMb29rIGZvciBpbmZsdWVudGlhbCBvYnNlcnZhdGlvbnMNCg0KI0xvb2tpbmcgYXQgb2JzZXJ2YXRpb24gMTI5OSw1MjQsIGRlbGV0ZSB0aGVtIGluIHRoZSBkYXRhDQpkYXRhPSBkYXRhWy1jKDEyOTksNTI0KSxdDQpyb3duYW1lcyhkYXRhKSA8LSBOVUxMDQojd3JpdGUuY3N2KGRhdGEsZmlsZSA9ICJ0cmFpbjEyMyIpDQojY29sbmFtZXMoZGF0YVtzYXBwbHkoY29tYmluZWRfZGF0YSwgaXMuZmFjdG9yKV0pDQpgYGANCg0KDQojIExvZ2dpbmcgU2FsZVByaWNlIHRvIHNlZSBpZiBpdCBmaXggdGhlIGNsdXN0ZXJyZWQgcmVzaWR1YWxzDQpgYGB7cix3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KZGF0YTI9ZGF0YQ0KZGF0YTIkU2FsZVByaWNlID0gbG9nKGRhdGEkU2FsZVByaWNlKQ0KbW9kZWwyID0gbG0oU2FsZVByaWNlfi4sIGRhdGEgPSBkYXRhMikNCiNzdW1tYXJ5KG1vZGVsMikNCnJlc2lkdWFsUGxvdChtb2RlbDIpDQojd3JpdGUuY3N2KGRhdGEyLGZpbGU9ImxvZ2RhdGEuY3N2Iixyb3cubmFtZXMgPSBGQUxTRSkNCg0KIyBDb21wYXJlIHRvIG1vZGVsMSh1bmxvZ2dlZCkgLCB0aGUgcmVzaWR1YWwgcGxvdHMgZm9ybXMgYSByYXRoZXIgcGVyZmVjdCByYW5kb20gY2xvdWQgZm9ybWF0aW9uIHdoaWNoIGlzIGlkZWFsDQojIEhpc3RvZ3JhbQ0KcmVzMj0gbW9kZWwyJHJlc2lkdWFscw0KaGlzdG9ncmFtKHJlczIpDQoNCnBsb3QobW9kZWwyKQ0KYGBgDQoNCg0KDQoNCg0KIyBQZXJmb3JtIGEgZm9yd2FyZC9iYWNrd2FyZC9zdGVwd2lzZSBzZWxlY3Rpb24gaW4gU0FTDQoNCiFbRGlhbm9zdGljc10odGFibGUucG5nKQ0KDQoNCg0KIyBCdWlsZCBjdXN0b20gcmVncmVzc2lvbiBtb2RlbCBpbiBTQVMNCg0KYGBge3J9DQptb2RlbF9mb3JtdWxhPSBsbShTYWxlUHJpY2UgfiBNU1pvbmluZzpHckxpdkFyZWErIExvdEFyZWE6QnNtdEZpblNGMStLaXRjaGVuQWJ2R3I6R2FyYWdlUXVhbCArR3JMaXZBcmVhOkxvdEFyZWErIExvdEFyZWEgKyBPdmVyYWxsUXVhbCArIE92ZXJhbGxDb25kICsgWWVhckJ1aWx0ICArIEJzbXRFeHBvc3VyZSArIEJzbXRGaW5TRjEgK0JzbXRGaW5TRjIgK0hlYXRpbmdRQytCc210VW5mU0YgKyBHckxpdkFyZWEgKyBIYWxmQmF0aCArIEtpdGNoZW5BYnZHciArIEtpdGNoZW5RdWFsICsgR2FyYWdlQXJlYSArIEdhcmFnZVF1YWwgKyBXb29kRGVja1NGICsNCiAgICAgICAgICAgICAgIFNjcmVlblBvcmNoICArIE1TWm9uaW5nICArIE5laWdoYm9yaG9vZCAgKyBCbGRnVHlwZSArDQogICAgICAgICAgICAgICBNYXNWbnJUeXBlICsgRm91bmRhdGlvbiArIEZ1bmN0aW9uYWwgKyBHYXJhZ2VUeXBlICArIFNhbGVDb25kaXRpb24rRmlyZXBsYWNlcywNCiAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhMikgICAgICAgICAgIA0KDQoNCg0KDQpgYGANCg0KDQojIFByZWRpdGlvbg0KYGBge3J9DQoNCnRhYmxlKGRhdGEkTVNab25pbmcpDQp0YWJsZSh0ZXN0JE1TWm9uaW5nKQ0KbGV2ZWxzKHRlc3QkTVNab25pbmcpW2lzLm5hKGxldmVscyh0ZXN0JE1TWm9uaW5nKSldIDwtICJSTCINCg0KDQp0YWJsZShkYXRhJEV4dGVyaW9yMXN0ICkNCnRhYmxlKHRlc3QkRXh0ZXJpb3Ixc3QgKQ0KbGV2ZWxzKHRlc3QkRXh0ZXJpb3Ixc3QpW2lzLm5hKGxldmVscyh0ZXN0JEV4dGVyaW9yMXN0KSldIDwtICJWaW55bFNkIg0KDQp0YWJsZShkYXRhJEZ1bmN0aW9uYWwgICkNCnRhYmxlKHRlc3QkRnVuY3Rpb25hbCAgKQ0KbGV2ZWxzKHRlc3QkRnVuY3Rpb25hbCApW2lzLm5hKGxldmVscyh0ZXN0JEZ1bmN0aW9uYWwgKSldIDwtICJUeXAiDQoNCnRhYmxlKGRhdGEkU2FsZVR5cGUgICApDQp0YWJsZSh0ZXN0JFNhbGVUeXBlICAgKQ0KbGV2ZWxzKHRlc3QkU2FsZVR5cGUgIClbaXMubmEobGV2ZWxzKHRlc3QkU2FsZVR5cGUgICkpXSA8LSAiV0QiDQojRm9yd2FyZA0KDQpsbV9wcmVkaWN0X21vZGVsPSBsbShTYWxlUHJpY2UgfiBNU1N1YkNsYXNzICsgTG90QXJlYSArIE92ZXJhbGxRdWFsICsgT3ZlcmFsbENvbmQgKyBZZWFyQnVpbHQgKyBNYXNWbnJBcmVhICsgRXh0ZXJRdWFsICsNCiAgICAgICAgICAgICAgIEJzbXRRdWFsICsgQnNtdENvbmQgKyBCc210RXhwb3N1cmUgKyBCc210RmluU0YxICsgVG90YWxCc210U0YgKyBHckxpdkFyZWEgKyBIYWxmQmF0aCArDQogICAgICAgICAgICAgICBCZWRyb29tQWJ2R3IgKyBLaXRjaGVuQWJ2R3IgKyBLaXRjaGVuUXVhbCArIEdhcmFnZUFyZWEgKyBHYXJhZ2VRdWFsICsgV29vZERlY2tTRiArDQogICAgICAgICAgICAgICBTY3JlZW5Qb3JjaCArIE1vU29sZCArIE1TWm9uaW5nICsgTG90Q29uZmlnICsgTmVpZ2hib3Job29kICsgQ29uZGl0aW9uMSArIEJsZGdUeXBlICsNCiAgICAgICAgICAgICAgIEV4dGVyaW9yMXN0ICsgTWFzVm5yVHlwZSArIEZvdW5kYXRpb24gKyBGdW5jdGlvbmFsICsgR2FyYWdlVHlwZSArIFBhdmVkRHJpdmUgKyBTYWxlQ29uZGl0aW9uLA0KICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEyKQ0KI3N1bW1hcnkobG1fcHJlZGljdF9tb2RlbCkNCg0KIA0KIA0KcHJlZGljaXRvbj1wcmVkaWN0KGxtX3ByZWRpY3RfbW9kZWwsbmV3ZGF0YSA9IHRlc3QpDQoNCg0KdGVzdCRTYWxlUHJpY2U9ZXhwKHByZWRpY2l0b24pDQpTdWJtaXNzaW9uX0Y9dGVzdFssYygiSWQiLCJTYWxlUHJpY2UiKV0NCg0KbWVhbl9zYWxlX3ByaWNlIDwtIG1lYW4oU3VibWlzc2lvbl9GJFNhbGVQcmljZSwgbmEucm0gPSBUUlVFKQ0KU3VibWlzc2lvbl9GJFNhbGVQcmljZVtpcy5uYShTdWJtaXNzaW9uX0YkU2FsZVByaWNlKV0gPC0gbWVhbl9zYWxlX3ByaWNlDQoNCnN1bShpcy5uYShwcmVkaWNpdG9uKSkNCndyaXRlLmNzdihTdWJtaXNzaW9uX0YsIGZpbGUgPSAnU3VibWlzc2lvbl9GLmNzdicsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQoNCg0KcGxvdChsbV9wcmVkaWN0X21vZGVsJHJlc2lkdWFscykNCnFxUGxvdChsbV9wcmVkaWN0X21vZGVsKQ0KaGlzdG9ncmFtKGxtX3ByZWRpY3RfbW9kZWwkcmVzaWR1YWxzKQ0KcGxvdChsbV9wcmVkaWN0X21vZGVsKQ0KDQoNCg0KDQojQmFja3dhcmQNCg0KbW9kZWxfZm9ybXVsYSA8LSBsbSggU2FsZVByaWNlIH4gTVNTdWJDbGFzcyArIExvdEZyb250YWdlICsgTG90QXJlYSArIExhbmRTbG9wZSArIE92ZXJhbGxRdWFsICsgT3ZlcmFsbENvbmQgKyBZZWFyQnVpbHQgKyBNYXNWbnJBcmVhICsgRXh0ZXJRdWFsICsgRXh0ZXJDb25kICsgQnNtdFF1YWwgKyBCc210Q29uZCArIEJzbXRFeHBvc3VyZSArIEJzbXRGaW5TRjEgKyBCc210RmluU0YyICsgQnNtdFVuZlNGICsgSGVhdGluZ1FDICsgWDJuZEZsclNGICsgTG93UXVhbEZpblNGICsgR3JMaXZBcmVhICsgRnVsbEJhdGggKyBIYWxmQmF0aCArIEJlZHJvb21BYnZHciArIEtpdGNoZW5BYnZHciArIEtpdGNoZW5RdWFsICsgVG90Um1zQWJ2R3JkICsgRmlyZXBsYWNlcyArIEdhcmFnZUFyZWEgKyBHYXJhZ2VRdWFsICsgV29vZERlY2tTRiArIE9wZW5Qb3JjaFNGICsgWDNTc25Qb3JjaCArIFNjcmVlblBvcmNoICsgUG9vbEFyZWEgKyBNb1NvbGQgKyBNU1pvbmluZyArIExhbmRDb250b3VyICsgTG90Q29uZmlnICsgTmVpZ2hib3Job29kICsgQ29uZGl0aW9uMSArIEJsZGdUeXBlICsgSG91c2VTdHlsZSArIFJvb2ZNYXRsICsgRXh0ZXJpb3Ixc3QgKyBNYXNWbnJUeXBlICsgRm91bmRhdGlvbiArIEZ1bmN0aW9uYWwgKyBHYXJhZ2VUeXBlICsgU2FsZVR5cGUgKyBTYWxlQ29uZGl0aW9uDQosZGF0YSA9IGRhdGEyKQ0KI3N1bW1hcnkobW9kZWxfZm9ybXVsYSkNCnByZWRpY2l0b249cHJlZGljdChtb2RlbF9mb3JtdWxhLG5ld2RhdGEgPSB0ZXN0KQ0KDQp0ZXN0JFNhbGVQcmljZT1leHAocHJlZGljaXRvbikNCnN1Ym1pc3Npb25fQmFja3dhcmQ9dGVzdFssYygiSWQiLCJTYWxlUHJpY2UiKV0NCg0KbWVhbl9zYWxlX3ByaWNlIDwtIG1lYW4oc3VibWlzc2lvbl9CYWNrd2FyZCRTYWxlUHJpY2UsIG5hLnJtID0gVFJVRSkNCnN1Ym1pc3Npb25fQmFja3dhcmQkU2FsZVByaWNlW2lzLm5hKHN1Ym1pc3Npb25fQmFja3dhcmQkU2FsZVByaWNlKV0gPC0gbWVhbl9zYWxlX3ByaWNlDQoNCnN1bShpcy5uYShwcmVkaWNpdG9uKSkNCndyaXRlLmNzdihzdWJtaXNzaW9uX0JhY2t3YXJkLCBmaWxlID0gJ3N1Ym1pc3Npb25fQmFja3dhcmQuY3N2Jywgcm93Lm5hbWVzID0gRkFMU0UpDQoNCg0KcGxvdChtb2RlbF9mb3JtdWxhJHJlc2lkdWFscykNCnFxUGxvdChtb2RlbF9mb3JtdWxhKQ0KaGlzdG9ncmFtKG1vZGVsX2Zvcm11bGEkcmVzaWR1YWxzKQ0KcGxvdChtb2RlbF9mb3JtdWxhKQ0KDQojc3RlcHdpc2UNCg0KbW9kZWxfZm9ybXVsYSA8LSBsbShTYWxlUHJpY2UgfiBNU1N1YkNsYXNzICsgTG90RnJvbnRhZ2UgKyBMb3RBcmVhICsgTGFuZFNsb3BlICsgT3ZlcmFsbFF1YWwgKyBPdmVyYWxsQ29uZCArIFllYXJCdWlsdCArIE1hc1ZuckFyZWEgKyBFeHRlclF1YWwgKyBFeHRlckNvbmQgKyBCc210UXVhbCArIEJzbXRDb25kICsgQnNtdEV4cG9zdXJlICsgQnNtdEZpblNGMSArIEJzbXRGaW5TRjIgKyBUb3RhbEJzbXRTRiArIEdyTGl2QXJlYSArIEJlZHJvb21BYnZHciArIEtpdGNoZW5BYnZHciArIEtpdGNoZW5RdWFsICsgR2FyYWdlQXJlYSArIEdhcmFnZVF1YWwgKyBXb29kRGVja1NGICsgT3BlblBvcmNoU0YgKyBNb1NvbGQgKyBNU1pvbmluZyArIExvdENvbmZpZyArIE5laWdoYm9yaG9vZCArIENvbmRpdGlvbjEgKyBCbGRnVHlwZSArIEV4dGVyaW9yMXN0ICsgTWFzVm5yVHlwZSArIEZ1bmN0aW9uYWwgKyBHYXJhZ2VUeXBlICsgUGF2ZWREcml2ZSArIFNhbGVDb25kaXRpb24sZGF0YSA9IGRhdGEyKQ0KI3N1bW1hcnkobW9kZWxfZm9ybXVsYSkNCg0KcHJlZGljaXRvbj1wcmVkaWN0KG1vZGVsX2Zvcm11bGEsbmV3ZGF0YSA9IHRlc3QpDQoNCnRlc3QkU2FsZVByaWNlPWV4cChwcmVkaWNpdG9uKQ0Kc3VibWlzc2lvbl9zdGVwd2lzZT10ZXN0WyxjKCJJZCIsIlNhbGVQcmljZSIpXQ0KDQptZWFuX3NhbGVfcHJpY2UgPC0gbWVhbihzdWJtaXNzaW9uX3N0ZXB3aXNlJFNhbGVQcmljZSwgbmEucm0gPSBUUlVFKQ0Kc3VibWlzc2lvbl9zdGVwd2lzZSRTYWxlUHJpY2VbaXMubmEoc3VibWlzc2lvbl9zdGVwd2lzZSRTYWxlUHJpY2UpXSA8LSBtZWFuX3NhbGVfcHJpY2UNCg0Kc3VtKGlzLm5hKHByZWRpY2l0b24pKQ0Kd3JpdGUuY3N2KHN1Ym1pc3Npb25fc3RlcHdpc2UsIGZpbGUgPSAnc3VibWlzc2lvbl9zdGVwd2lzZS5jc3YnLCByb3cubmFtZXMgPSBGQUxTRSkNCg0KcGxvdChtb2RlbF9mb3JtdWxhJHJlc2lkdWFscykNCnFxUGxvdChtb2RlbF9mb3JtdWxhKQ0KaGlzdG9ncmFtKG1vZGVsX2Zvcm11bGEkcmVzaWR1YWxzKQ0KcGxvdChtb2RlbF9mb3JtdWxhKQ0KI0N1c3RvbQ0KDQoNCg0KbW9kZWxfZm9ybXVsYT0gbG0oU2FsZVByaWNlIH4gTVNab25pbmc6R3JMaXZBcmVhKyBMb3RBcmVhOkJzbXRGaW5TRjErS2l0Y2hlbkFidkdyOkdhcmFnZVF1YWwgK0dyTGl2QXJlYTpMb3RBcmVhKyBMb3RBcmVhICsgT3ZlcmFsbFF1YWwgKyBPdmVyYWxsQ29uZCArIFllYXJCdWlsdCAgKyBCc210RXhwb3N1cmUgKyBCc210RmluU0YxICtCc210RmluU0YyICtIZWF0aW5nUUMrQnNtdFVuZlNGICsgR3JMaXZBcmVhICsgSGFsZkJhdGggKyBLaXRjaGVuQWJ2R3IgKyBLaXRjaGVuUXVhbCArIEdhcmFnZUFyZWEgKyBHYXJhZ2VRdWFsICsgV29vZERlY2tTRiArDQogICAgICAgICAgICAgICBTY3JlZW5Qb3JjaCAgKyBNU1pvbmluZyAgKyBOZWlnaGJvcmhvb2QgICsgQmxkZ1R5cGUgKw0KICAgICAgICAgICAgICAgTWFzVm5yVHlwZSArIEZvdW5kYXRpb24gKyBGdW5jdGlvbmFsICsgR2FyYWdlVHlwZSAgKyBTYWxlQ29uZGl0aW9uK0ZpcmVwbGFjZXMsDQogICAgICAgICAgICAgICBkYXRhID0gZGF0YTIpICAgICAgICAgICANCiNzdW1tYXJ5KG1vZGVsX2Zvcm11bGEpDQoNCiANCnByZWRpY2l0b249cHJlZGljdChtb2RlbF9mb3JtdWxhLG5ld2RhdGEgPSB0ZXN0KSAgDQoNCnRlc3QkU2FsZVByaWNlPWV4cChwcmVkaWNpdG9uKQ0Kc3VibWlzc2lvbl9DdXN0PXRlc3RbLGMoIklkIiwiU2FsZVByaWNlIildDQoNCm1lYW5fc2FsZV9wcmljZSA8LSBtZWFuKHN1Ym1pc3Npb25fQ3VzdCRTYWxlUHJpY2UsIG5hLnJtID0gVFJVRSkNCnN1Ym1pc3Npb25fQ3VzdCRTYWxlUHJpY2VbaXMubmEoc3VibWlzc2lvbl9DdXN0JFNhbGVQcmljZSldIDwtIG1lYW5fc2FsZV9wcmljZQ0KDQpzdW0oaXMubmEocHJlZGljaXRvbikpDQp3cml0ZS5jc3Yoc3VibWlzc2lvbl9DdXN0LCBmaWxlID0gJ3N1Ym1pc3Npb25fQ3VzdC5jc3YnLCByb3cubmFtZXMgPSBGQUxTRSkNCg0KcGxvdChtb2RlbF9mb3JtdWxhKQ0KcGxvdChtb2RlbF9mb3JtdWxhJHJlc2lkdWFscykNCmhpc3RvZ3JhbShtb2RlbF9mb3JtdWxhJHJlc2lkdWFscykNCg0KDQojdHJpYWwyDQoNCm1vZGVsX2Zvcm11bGE9IGxtKFNhbGVQcmljZSB+IChZZWFyQnVpbHQ6U2NyZWVuUG9yY2grTG90QXJlYTpUb3RhbEJzbXRTRitLaXRjaGVuQWJ2R3I6R2FyYWdlUXVhbCArR3JMaXZBcmVhOkxvdEFyZWErIExvdEFyZWEgKyBPdmVyYWxsUXVhbCArIE92ZXJhbGxDb25kICsgWWVhckJ1aWx0ICArIEJzbXRFeHBvc3VyZSArIEJzbXRGaW5TRjEgK0JzbXRGaW5TRjIgK0hlYXRpbmdRQytCc210VW5mU0YgKyBHckxpdkFyZWEgKyBIYWxmQmF0aCArIEtpdGNoZW5BYnZHciArIEtpdGNoZW5RdWFsICsgR2FyYWdlQXJlYSArIEdhcmFnZVF1YWwgKyBXb29kRGVja1NGICsNCiAgICAgICAgICAgICAgIFNjcmVlblBvcmNoICArIE1TWm9uaW5nICArIE5laWdoYm9yaG9vZCAgKyBCbGRnVHlwZSArDQogICAgICAgICAgICAgICBNYXNWbnJUeXBlICsgRm91bmRhdGlvbiArIEZ1bmN0aW9uYWwgKyBHYXJhZ2VUeXBlICArIFNhbGVDb25kaXRpb24rRmlyZXBsYWNlcyleMiwNCiAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhMikgIA0KI3N1bW1hcnkobW9kZWxfZm9ybXVsYSkNCg0KcHJlZGljaXRvbj1wcmVkaWN0KG1vZGVsX2Zvcm11bGEsbmV3ZGF0YSA9IHRlc3QpICANCg0KdGVzdCRTYWxlUHJpY2U9ZXhwKHByZWRpY2l0b24pDQpzdWJtaXNzaW9uX0N1c3Q9dGVzdFssYygiSWQiLCJTYWxlUHJpY2UiKV0NCg0KbWVhbl9zYWxlX3ByaWNlIDwtIG1lYW4oc3VibWlzc2lvbl9DdXN0JFNhbGVQcmljZSwgbmEucm0gPSBUUlVFKQ0Kc3VibWlzc2lvbl9DdXN0JFNhbGVQcmljZVtpcy5uYShzdWJtaXNzaW9uX0N1c3QkU2FsZVByaWNlKV0gPC0gbWVhbl9zYWxlX3ByaWNlDQoNCnN1bShpcy5uYShwcmVkaWNpdG9uKSkNCndyaXRlLmNzdihzdWJtaXNzaW9uX0N1c3QsIGZpbGUgPSAnc3VibWlzc2lvbl9DdXN0LmNzdicsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQoNCmBgYA0KDQoNCg0KDQojIEV4YW1lbiByZWxhdGlvbnNoaXAgaW4gU2FsZXMgcHJpY2UgaW4gbmVpZ2hib3Job29kICdOQW1lcycsICdFZHdhcmRzJywgJ0Jya1NpZGUnIA0KYGBge3Isd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCm9wdGlvbnMoc2NpcGVuID0gOTk5KQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCg0KZGF0YT0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9hbmlzaGthcGV0ZXIvU3RhdDFQcm9qZWN0L21haW4vdHJhaW4uY3N2IikNCg0KIyBNb2RlbCB3aXRob3V0IEludGVyYWN0aW9uIFZhcmlhYmxlIA0KZmlsdGVyZWRfbmVpZ2hib3Job29kID0gZGF0YSAlPiUgZmlsdGVyIChOZWlnaGJvcmhvb2QgJWluJSBjKCdOQW1lcycsICdFZHdhcmRzJywgJ0Jya1NpZGUnKSkNCg0KZmlsdGVyZWRfbmVpZ2hib3Job29kX21vZGVsPSBsbShTYWxlUHJpY2UgfiBHckxpdkFyZWEsIGRhdGEgPSBmaWx0ZXJlZF9uZWlnaGJvcmhvb2QpDQojc3VtbWFyeShmaWx0ZXJlZF9uZWlnaGJvcmhvb2RfbW9kZWwpDQoNCiMgQ2hlY2sgQXNzdW1wdGlvbnMgTW9kZWwgV2l0aG91dCBJbmRpY2F0b3IgYW5kIEludGVyYWN0aW9uIFZhcmlhYmxlICANCnBsb3QoZmlsdGVyZWRfbmVpZ2hib3Job29kX21vZGVsKQ0KDQpoaXN0b2dyYW0oZmlsdGVyZWRfbmVpZ2hib3Job29kX21vZGVsJHJlc2lkdWFscykNCg0KZ2dwbG90KGZpbHRlcmVkX25laWdoYm9yaG9vZCxhZXMoeCA9R3JMaXZBcmVhICwgeSA9U2FsZVByaWNlICkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdndGl0bGUoIlNjYXR0ZXJQbG90IG9mIFNhbGVQcmljZSB2cyBHckxpdkFyZWEiKSANCg0KIyBSZXNpZHVhbCBwbG90IGNsdXN0ZXJlZCwgdXNpbmcgbG9nLWxvZyBtZXRob2QgdG8gdHJhbnNmb3JtIHRoZSBkYXRhc2V0DQoNCiMgTG9nIGxvZyBUcmFuc2Zvcm0gdG8gZGF0YSANCmRhdGEzPWRhdGENCmRhdGEzJFNhbGVQcmljZSA9IGxvZyhkYXRhJFNhbGVQcmljZSkNCmRhdGEzJEdyTGl2QXJlYSA9IGxvZyhkYXRhJEdyTGl2QXJlYSkNCg0KIyBmaWx0ZXIgdGhlIGxvZ2dlZCBkYXRhIHRvIG9ubHkgaW5jbHVkZSB0aGUgMyBuZWlnaGJvcmhvb2RzIG9mIGludGVyZXN0DQpmaWx0ZXJlZF9kYXRhMiA8LSBkYXRhMyAlPiUgZmlsdGVyKE5laWdoYm9yaG9vZCAlaW4lIGMoJ05BbWVzJywgJ0Vkd2FyZHMnLCAnQnJrU2lkZScpKQ0KDQojIGJ1aWxkIG1vZGVsIG9uIGxvZyBkYXRhIHdpdGhvdXQgaW50ZXJhY3Rpb24gYW5kIGluZGljYXRvciB2YXINCmZpbHRlcmVkX2RhdGEyX21vZGVsID0gbG0oU2FsZVByaWNlIH4gR3JMaXZBcmVhLCBkYXRhID0gZmlsdGVyZWRfZGF0YTIpDQojc3VtbWFyeShmaWx0ZXJlZF9kYXRhMl9tb2RlbCkNCg0KIyBDaGVja2luZyBBc3N1bXB0aW9ucyANCmdncGxvdChmaWx0ZXJlZF9kYXRhMixhZXMoeCA9R3JMaXZBcmVhICwgeSA9U2FsZVByaWNlICkpICsNCiAgZ2VvbV9wb2ludCgpK2dndGl0bGUoIlNjYXR0ZXJQbG90IG9mIExvZyhTYWxlUHJpY2UpIHZzIExvZyhHckxpdkFyZWEpIikgKyANCiAgeGxhYigiTG9nKEdyTGl2QXJlYSkiKSArDQogIHlsYWIoIkxvZyhTYWxlUHJpY2UpIikNCg0KaGlzdChmaWx0ZXJlZF9kYXRhMl9tb2RlbCRyZXNpZHVhbHMpDQoNCnBsb3QoZmlsdGVyZWRfZGF0YTJfbW9kZWwpDQoNCg0KIyBDb25maWRlbmNlIEludGVydmFsIGZvciBMb2cgTW9kZWwgd2l0aG91dCBJbnRlcmFjdGlvbiBvciBJbmRpY2F0b3INCmNvbmZpbnQoZmlsdGVyZWRfZGF0YTJfbW9kZWwpDQoNCnBsb3QoZmlsdGVyZWRfZGF0YTIkR3JMaXZBcmVhLCBmaWx0ZXJlZF9kYXRhMiRTYWxlUHJpY2UsIA0KICAgICBtYWluPSJTY2F0dGVycGxvdCB3aXRoIFJlZ3Jlc3Npb24gTGluZSIsIA0KICAgICB4bGFiPSJBYm92ZSBncmFkZSAoZ3JvdW5kKSBsaXZpbmcgYXJlYSBzcXVhcmUgZmVldCAoR3JMaXZBcmVhKSIsIA0KICAgICB5bGFiPSJTYWxlIFByaWNlIChTYWxlUHJpY2UpIiwgcGNoPTE5LCBmcmFtZT1GQUxTRSwgY29sPSJibHVlIikrDQogIGFibGluZShmaWx0ZXJlZF9kYXRhMl9tb2RlbCwgY29sPSJyZWQiKQ0KDQoNCmBgYA0KIyMjIyBUaGVyZWZvcmUgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgcHJlZGljdGluZyBTYWxlUHJpY2UgdXNpbmcgR3JsaXZBcmVhIGlzIA0KU2FsZVByaWNlID0gNy41ODQzNyArIDAuNTkyMzAgKiBHcmxpdkFyZWENCg0KIyBBZGRpbmcgSW5kaWNhdG9yIFZhcmlhYmxlIA0KYGBge3J9DQojIEFkZGluZyBJbmRpY2F0b3IgVmFyaWFibGUgDQpmaWx0ZXJlZF9kYXRhMl9tb2RlbDMgPC0gbG0oU2FsZVByaWNlIH4gIEdyTGl2QXJlYSArIE5laWdoYm9yaG9vZCwgZGF0YSA9IGZpbHRlcmVkX2RhdGEyKQ0KI3N1bW1hcnkoZmlsdGVyZWRfZGF0YTJfbW9kZWwzKQ0KDQpgYGANCg0KDQojIEFkZGluZyBpbnRlcmFjdGlvbiB2YXJpYWJsZXMNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KDQojIEZpdCB0aGUgbW9kZWwNCmZpbHRlcmVkX2RhdGEyX21vZGVsMiA8LSBsbShTYWxlUHJpY2UgfiAgR3JMaXZBcmVhICsgR3JMaXZBcmVhICogTmVpZ2hib3Job29kLCBkYXRhID0gZmlsdGVyZWRfZGF0YTIpDQoNCiMgU3VtbWFyeSBvZiB0aGUgbW9kZWwNCiNzdW1tYXJ5KGZpbHRlcmVkX2RhdGEyX21vZGVsMikNCg0KIyBDb25maWRlbmNlIGludGVydmFscw0KY29uZmludChmaWx0ZXJlZF9kYXRhMl9tb2RlbDIpDQoNCg0KIyBSZXNpZHVhbHMgaGlzdG9ncmFtDQpoaXN0b2dyYW0gPC0gZ2dwbG90KGZpbHRlcmVkX2RhdGEyX21vZGVsMiwgYWVzKHg9cmVzaWR1YWxzKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aD0xLCBjb2xvcj0iYmxhY2siLCBmaWxsPSJ3aGl0ZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh4PSJSZXNpZHVhbHMiLCB5PSJGcmVxdWVuY3kiLCB0aXRsZT0iSGlzdG9ncmFtIG9mIFJlc2lkdWFscyIpDQoNCiMgTW9kZWwgZGlhZ25vc3RpY3MNCnBsb3RfZGlhZyA8LSBwbG90KGZpbHRlcmVkX2RhdGEyX21vZGVsMiwgZGlhZ25vc3RpYyA9IFRSVUUpDQoNCg0KIyBNb2RlbCBDb2VmZmljaWVudHMNCm1vZGVsX2NvZWYgPC0gY29lZihmaWx0ZXJlZF9kYXRhMl9tb2RlbDIpDQpgYGANCg0KIyMgQW5vdmEgQW5hbHlzaXMgDQpgYGB7cn0NCiNBTk9WQSBmb3IgbW9kZWwgd2l0aCBOZWlnaGJvcmhvb2QgYXMgSW50ZXJhY3Rpb24gVmFyaWFibGUgDQphbm92YShmaWx0ZXJlZF9kYXRhMl9tb2RlbDMpDQoNCiNBTk9WQSBmb3IgbW9kZWwgd2l0aCBOZWlnaGJvcmhvb2QgYXMgSW5kaWNhdG9yIFZhcmlhYmxlIA0KYW5vdmEoZmlsdGVyZWRfZGF0YTJfbW9kZWwyKQ0KDQojQU5PVkEgZm9yIG1vZGVsIHdpdGhvdXQgTmVpZ2hib3Job29kICANCmFub3ZhKGZpbHRlcmVkX2RhdGEyX21vZGVsKQ0KDQoxIC0gcGYoNjguMDI5NzI5NzMsMiwzNzcpDQoNCjEgLSBwZig4LjY0MTg5MTg5MiwyLDM3NykNCg0KDQpgYGANCg0KDQojIE1vZGVsIHdpdGggSW50ZXJhY3Rpb24gU3VtbWFyaWVzIA0KDQpGb3Igb3VyIGJlc3QgcGVyZm9ybWluZyBtb2RlbCB3ZSBoYWQgIzEyODggb24gS2FnZ2xlLCBZYWghDQohW0RpYW5vc3RpY3NdKGthZ2dsZXNjb3JlLnBuZykNCg0KIyMjIyBGb3IgZWFjaCBuZWlnaGJvcmhvb2QsIHRoZSByZWdyZXNzaW9uIG1vZGVsIHByZWRpY3RpbmcgU2FsZVByaWNlIHVzaW5nIEdyTGl2QXJlYSBpcyBnaXZlbiBieToNCg0KIyMjIyBOZWlnaGJvcmhvb2QgJ0Jya1NpZGUnOg0KDQpsb2dTYWxlUHJpY2UgPSAgNS45MTI5MiArIDAuODE5NjUqbG9nR3JMaXZBcmVhDQoNCiMjIyMjIEludGVycHJldGF0aW9uIG9mIHRoZSBDb2VmZmljaWVudHMgDQpFdmVyeSB0aW1lIHRoZSBzcXVhcmUgZm9vdGFnZSBvZiB0aGUgbGl2aW5nIGFyZWEgZG91YmxlcywgdGhlcmUgaXMgYW4gZXN0aW1hdGVkIG11bHRpcGxpY2F0aXZlIGluY3JlYXNlIG9mIDEuNzY0OTc3NzU0MzYgKGFib3V0IDc2LjUlIGluY3JlYXNlKSBpbiB0aGUgbWVkaWFuIFNhbGUgUHJpY2UuICANCg0KV2hlbiB0aGUgc3F1YXJlIGZvb3RhZ2Ugb2YgdGhlIGxpdmluZyBhcmVhIGlzIDAsIHRoZSBlc3RpbWF0ZWQgbWVkaWFuIFNhbGVQcmljZSAzNjkuNzg0MzUuIA0KDQojIyMjIyBJbnRlcnByZXRhdGlvbiBvZiBDb25maWRlbmNlIEludGVydmFscyAgIA0KRXZlcnkgdGltZSB0aGUgc3F1YXJlIGZvb3RhZ2Ugb2YgdGhlIGxpdmluZyBhcmVhIGRvdWJsZXMsIHRoZSBlc3RpbWF0ZWQgbXVsdGlwbGljYXRpdmUgaW5jcmVhc2UgaW4gbWVkaWFuIFNhbGVzIFByaWNlIGZvciBCcm9va2VzaWRlIGlzIGJldHdlZW4gMS42MDA4MTQ3ODgyOSBhbmQgMS45NDU5NzAzMTE1Ni4gDQoNCldoZW4gdGhlIHNxdWFyZSBmb290YWdlIG9mIHRoZSBsaXZpbmcgYXJlYSBpcyAwLiwgdGhlIGVzdGltYXRlZCBtZWRpYW4gU2FsZSBQcmljZSBpcyBiZXR3ZWVuIDEzNy4xMDYzOTA4NSBhbmQgOTk3LjMzMjU4NDkwOCBpbiBCcm9va3NpZGUgbmVpZ2hib3Job29kLiAgDQoNCg0KIyMjIyBOZWlnaGJvcmhvb2QgJ05BbWVzJzoNCmxvZ1NhbGVQcmljZSA9IDcuNzQ3ODQgKyAwLjQ3MzAzKmxvZ0dyTGl2QXJlYQ0KDQoNCiMjIyMjIEludGVycHJldGF0aW9uIG9mIHRoZSBDb2VmZmljaWVudHMgDQpFdmVyeSB0aW1lIHRoZSBzcXVhcmUgZm9vdGFnZSBvZiB0aGUgbGl2aW5nIGFyZWEgZG91YmxlcywgdGhlcmUgaXMgYW4gZXN0aW1hdGVkIG11bHRpcGxpY2F0aXZlIGluY3JlYXNlIG9mIDEuMzg4MDIxNTgxODEsIChhYm91dCAzOC44JSBpbmNyZWFzZSkgaW4gdGhlIG1lZGlhbiBTYWxlIFByaWNlLiAgDQoNCldoZW4gdGhlIHNxdWFyZSBmb290YWdlIG9mIHRoZSBsaXZpbmcgYXJlYSBpcyAwLCB0aGUgZXN0aW1hdGVkIG1lZGlhbiBTYWxlUHJpY2UgNDg3OS4xNjgwMzY1NS4gDQoNCiMjIyMjIEludGVycHJldGF0aW9uIG9mIENvbmZpZGVuY2UgSW50ZXJ2YWxzICAgDQpXaGVuIHRoZSBzcXVhcmUgZm9vdGFnZSBvZiB0aGUgbGl2aW5nIGFyZWEgaXMgMCwgdGhlIGVzdGltYXRlZCBtZWRpYW4gU2FsZVByaWNlIDQ4NzkuMTY4MDM2NTUgLiANCg0KV2hlbiB0aGUgc3F1YXJlIGZvb3RhZ2Ugb2YgdGhlIGxpdmluZyBhcmVhIGlzIDAsIHRoZSBlc3RpbWF0ZWQgbWVkaWFuIFNhbGUgUHJpY2UgaXMgYmV0d2VlbiA1NTYuMTQ2NDE3MjcyIGFuZCA0MjgwNS41Nzc5OTIzIGluIE5vcnRoIEFtZXMgbmVpZ2hib3Job29kLiANCiANCg0KDQojIyMjIE5laWdoYm9yaG9vZCAnRWR3YXJkcyc6DQpsb2dTYWxlUHJpY2UgPSA4LjAwNjUxICsgMC41MTk2NyAqbG9nR3JMaXZBcmVhDQoNCiMjIyMjIEludGVycHJldGF0aW9uIG9mIHRoZSBDb2VmZmljaWVudHMgDQpFdmVyeSB0aW1lIHRoZSBzcXVhcmUgZm9vdGFnZSBvZiB0aGUgbGl2aW5nIGFyZWEgZG91YmxlcywgdGhlcmUgaXMgYW4gZXN0aW1hdGVkIG11bHRpcGxpY2F0aXZlIGluY3JlYXNlIG9mIDEuNDMzNjA3NDEwNSAoYWJvdXQgNDMuMzYlIGluY3JlYXNlKSBpbiB0aGUgbWVkaWFuIFNhbGUgUHJpY2UuICANCg0KV2hlbiB0aGUgc3F1YXJlIGZvb3RhZ2Ugb2YgdGhlIGxpdmluZyBhcmVhIGlzIDAsIHRoZSBlc3RpbWF0ZWQgbWVkaWFuIFNhbGUgUHJpY2UgMzAwMC40MjczMjc0OC4gIA0KDQojIyMjIyBDb25maWRlbmNlIEludGVydmFscyBhbmQgSW50ZXJwcmV0YXRpb24gDQoNCldoZW4gdGhlIHNxdWFyZSBmb290YWdlIG9mIHRoZSBsaXZpbmcgYXJlYSBpcyAwLCB0aGUgZXN0aW1hdGVkIG1lZGlhbiBTYWxlIFByaWNlIGlzIGJldHdlZW4gMzEyLjQxNjMzMzMzNSBhbmQgMjg4MTUuNzU2MDA0IGZvciBob3VzZXMgaW4gdGhlIEVkd2FyZHMgTmVpZ2hib3Job29kLiANCg0KRXZlcnkgdGltZSB0aGUgc3F1YXJlIGZvb3RhZ2Ugb2YgdGhlIGxpdmluZyBhcmVhIGRvdWJsZXMsIHRoZSBlc3RpbWF0ZWQgbXVsdGlwbGljYXRpdmUgaW5jcmVhc2UgaW4gbWVkaWFuIFNhbGVzIFByaWNlIGZvciBFZHdhcmRzIE5laWdoYm9yaG9vZCBpcyBiZXR3ZWVuIDEuMTQ4Mjc3MzEyOTkgYW5kIDEuNzg5ODgwNjYwOTQuIA0KDQoNCg0KDQoNCg0KZmlsdGVyZWRfZGF0YTINCmxpYnJhcnkoZ2dwbG90MikNCmZpbHRlcmVkX25laWdoYm9yaG9vZCAlPiUgDQogIGZpbHRlcihOZWlnaGJvcmhvb2QgPT0gIkJya1NpZGUiKSAlPiUgDQogIGdncGxvdChhZXMoeD1HckxpdkFyZWEsIHkgPSBTYWxlUHJpY2UpKSArIA0KICBnZW9tX3BvaW50KCBjb2xvciA9ICJzdGVlbGJsdWUiKSArIA0KICBnZ3RpdGxlKCJTYWxlIFByaWNlIHZzIExpdmluZyBBcmVhIFNxLkZ0IGluIEJyb29rc2lkZSIpICsNCiAgeGxhYigiU3F1YXJlIEZvb3RhZ2Ugb2YgTGl2aW5nIEFyZWEiKSArDQogIHlsYWIoIlNhbGVzIFByaWNlIGluIERvbGxhcnMiKQ0KDQoNCmZpbHRlcmVkX25laWdoYm9yaG9vZCAlPiUgDQogIGZpbHRlcihOZWlnaGJvcmhvb2QgPT0gIkVkd2FyZHMiKSAlPiUgDQogIGdncGxvdChhZXMoeD1HckxpdkFyZWEsIHkgPSBTYWxlUHJpY2UpKSArIA0KICBnZW9tX3BvaW50KCBjb2xvciA9ICJzdGVlbGJsdWUiKSArIA0KICBnZ3RpdGxlKCJTYWxlIFByaWNlIHZzIExpdmluZyBBcmVhIFNxLkZ0IGluIEVkd2FyZHMiKSArDQogIHhsYWIoIlNxdWFyZSBGb290YWdlIG9mIExpdmluZyBBcmVhIikgKw0KICB5bGFiKCJTYWxlcyBQcmljZSBpbiBEb2xsYXJzIikNCg0KZmlsdGVyZWRfbmVpZ2hib3Job29kICU+JSANCiAgZmlsdGVyKE5laWdoYm9yaG9vZCA9PSAiTkFtZXMiKSAlPiUgDQogIGdncGxvdChhZXMoeD1HckxpdkFyZWEsIHkgPSBTYWxlUHJpY2UpKSArIA0KICBnZW9tX3BvaW50KGNvbG9yID0gInN0ZWVsYmx1ZSIpICsgDQogIGdndGl0bGUoIlNhbGUgUHJpY2UgdnMgTGl2aW5nIEFyZWEgU3EuRnQgaW4gTm9ydGggQW1lcyIpICsNCiAgeGxhYigiU3F1YXJlIEZvb3RhZ2Ugb2YgTGl2aW5nIEFyZWEiKSArDQogIHlsYWIoIlNhbGVzIFByaWNlIGluIERvbGxhcnMiKQ0KDQoNCg0KDQoNCg==